package cn.com.anysdk.core.util;

import org.apache.commons.collections4.MapUtils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 集合工具类
 */
public class CollectionUtils {
    private CollectionUtils() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 判断集合是否为空
     *
     * @param collection 集合
     * @return 是否为空
     */
    public static boolean isEmpty(Collection<?> collection) {
        return org.apache.commons.collections4.CollectionUtils.isEmpty(collection);
    }

    /**
     * 判断集合是否不为空
     *
     * @param collection 集合
     * @return 是否不为空
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return org.apache.commons.collections4.CollectionUtils.isNotEmpty(collection);
    }

    /**
     * 判断Map是否为空
     *
     * @param map Map
     * @return 是否为空
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return MapUtils.isEmpty(map);
    }

    /**
     * 判断Map是否不为空
     *
     * @param map Map
     * @return 是否不为空
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return MapUtils.isNotEmpty(map);
    }

    /**
     * 获取集合大小
     *
     * @param collection 集合
     * @return 大小
     */
    public static int size(Collection<?> collection) {
        return collection != null ? collection.size() : 0;
    }

    /**
     * 获取Map大小
     *
     * @param map Map
     * @return 大小
     */
    public static int size(Map<?, ?> map) {
        return map != null ? map.size() : 0;
    }

    /**
     * 判断集合是否包含指定元素
     *
     * @param collection 集合
     * @param element 元素
     * @return 是否包含
     */
    public static boolean contains(Collection<?> collection, Object element) {
        return collection != null && collection.contains(element);
    }

    /**
     * 判断集合是否包含所有指定元素
     *
     * @param collection 集合
     * @param elements 元素集合
     * @return 是否包含所有
     */
    public static boolean containsAll(Collection<?> collection, Collection<?> elements) {
        return org.apache.commons.collections4.CollectionUtils.containsAll(collection, elements);
    }

    /**
     * 判断集合是否包含任一指定元素
     *
     * @param collection 集合
     * @param elements 元素集合
     * @return 是否包含任一
     */
    public static boolean containsAny(Collection<?> collection, Collection<?> elements) {
        return org.apache.commons.collections4.CollectionUtils.containsAny(collection, elements);
    }

    /**
     * 获取集合的交集
     *
     * @param a 集合a
     * @param b 集合b
     * @return 交集
     */
    public static <T> Collection<T> intersection(Collection<T> a, Collection<T> b) {
        return org.apache.commons.collections4.CollectionUtils.intersection(a, b);
    }

    /**
     * 获取集合的并集
     *
     * @param a 集合a
     * @param b 集合b
     * @return 并集
     */
    public static <T> Collection<T> union(Collection<T> a, Collection<T> b) {
        return org.apache.commons.collections4.CollectionUtils.union(a, b);
    }

    /**
     * 获取集合的差集
     *
     * @param a 集合a
     * @param b 集合b
     * @return 差集
     */
    public static <T> Collection<T> subtract(Collection<T> a, Collection<T> b) {
        return org.apache.commons.collections4.CollectionUtils.subtract(a, b);
    }

    /**
     * 将集合转换为List
     *
     * @param collection 集合
     * @return List
     */
    public static <T> List<T> toList(Collection<T> collection) {
        return collection != null ? new ArrayList<>(collection) : new ArrayList<>();
    }

    /**
     * 将集合转换为Set
     *
     * @param collection 集合
     * @return Set
     */
    public static <T> Set<T> toSet(Collection<T> collection) {
        return collection != null ? new HashSet<>(collection) : new HashSet<>();
    }

    /**
     * 将集合转换为Map
     *
     * @param collection 集合
     * @param keyMapper 键映射函数
     * @param valueMapper 值映射函数
     * @return Map
     */
    public static <T, K, V> Map<K, V> toMap(Collection<T> collection, Function<T, K> keyMapper, Function<T, V> valueMapper) {
        return collection != null ? collection.stream().collect(Collectors.toMap(keyMapper, valueMapper)) : new HashMap<>();
    }

    /**
     * 将集合转换为Map（值相同）
     *
     * @param collection 集合
     * @param keyMapper 键映射函数
     * @return Map
     */
    public static <T, K> Map<K, T> toMap(Collection<T> collection, Function<T, K> keyMapper) {
        return toMap(collection, keyMapper, Function.identity());
    }

    /**
     * 将集合按指定条件分组
     *
     * @param collection 集合
     * @param classifier 分组函数
     * @return 分组后的Map
     */
    public static <T, K> Map<K, List<T>> groupBy(Collection<T> collection, Function<T, K> classifier) {
        return collection != null ? collection.stream().collect(Collectors.groupingBy(classifier)) : new HashMap<>();
    }

    /**
     * 将集合按指定条件分组并转换值
     *
     * @param collection 集合
     * @param classifier 分组函数
     * @param valueMapper 值映射函数
     * @return 分组后的Map
     */
    public static <T, K, V> Map<K, List<V>> groupBy(Collection<T> collection, Function<T, K> classifier, Function<T, V> valueMapper) {
        return collection != null ? collection.stream().collect(Collectors.groupingBy(classifier, Collectors.mapping(valueMapper, Collectors.toList()))) : new HashMap<>();
    }

    /**
     * 过滤集合
     *
     * @param collection 集合
     * @param predicate 过滤条件
     * @return 过滤后的集合
     */
    public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) {
        return collection != null ? collection.stream().filter(predicate).collect(Collectors.toList()) : new ArrayList<>();
    }

    /**
     * 转换集合
     *
     * @param collection 集合
     * @param mapper 转换函数
     * @return 转换后的集合
     */
    public static <T, R> List<R> map(Collection<T> collection, Function<T, R> mapper) {
        return collection != null ? collection.stream().map(mapper).collect(Collectors.toList()) : new ArrayList<>();
    }

    /**
     * 获取集合的第一个元素
     *
     * @param collection 集合
     * @return 第一个元素
     */
    public static <T> T first(Collection<T> collection) {
        return isEmpty(collection) ? null : collection.iterator().next();
    }

    /**
     * 获取集合的最后一个元素
     *
     * @param collection 集合
     * @return 最后一个元素
     */
    public static <T> T last(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }
        if (collection instanceof List) {
            List<T> list = (List<T>) collection;
            return list.get(list.size() - 1);
        }
        T last = null;
        for (T element : collection) {
            last = element;
        }
        return last;
    }

    /**
     * 获取集合的随机元素
     *
     * @param collection 集合
     * @return 随机元素
     */
    public static <T> T random(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }
        int size = collection.size();
        int index = new Random().nextInt(size);
        if (collection instanceof List) {
            return ((List<T>) collection).get(index);
        }
        int i = 0;
        for (T element : collection) {
            if (i == index) {
                return element;
            }
            i++;
        }
        return null;
    }

    /**
     * 获取集合的随机元素（指定数量）
     *
     * @param collection 集合
     * @param count 数量
     * @return 随机元素集合
     */
    public static <T> List<T> random(Collection<T> collection, int count) {
        if (isEmpty(collection) || count <= 0) {
            return new ArrayList<>();
        }
        List<T> list = toList(collection);
        if (count >= list.size()) {
            return list;
        }
        Collections.shuffle(list);
        return list.subList(0, count);
    }
}